package com.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.api.member.MemberFeignService;
import com.sky.domain.WmsWareOrderTask;
import com.sky.domain.WmsWareOrderTaskDetail;
import com.sky.domain.WmsWareSku;
import com.sky.dto.SkuStockVO;
import com.sky.exception.BizException;
import com.sky.exception.HasNoStockException;
import com.sky.service.WmsPurchaseDetailService;
import com.sky.service.WmsWareOrderTaskDetailService;
import com.sky.service.WmsWareOrderTaskService;
import com.sky.service.WmsWareSkuService;
import com.sky.mapper.WmsWareSkuMapper;
import com.sky.to.member.MemberReceiveAddressTo;
import com.sky.to.rabbitmq.StockLockTo;
import com.sky.to.ware.SkuStockTo;
import com.sky.to.ware.StockTo;
import com.sky.utils.PageUtils;
import com.sky.utils.R;
import com.sky.utils.StringUtils;
import com.sky.vo.param.WareSkuVO;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Administrator
* @description 针对表【wms_ware_sku(商品库存)】的数据库操作Service实现
* @createDate 2024-06-30 16:47:16
*/
@Service
public class WmsWareSkuServiceImpl extends ServiceImpl<WmsWareSkuMapper, WmsWareSku> implements WmsWareSkuService{

    @Resource
    private MemberFeignService memberFeignService;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private WmsWareOrderTaskDetailService wareOrderTaskDetailService;
    @Resource
    private WmsWareOrderTaskService wareOrderTaskService;

    /**
     * 分页查询
     * @param vo
     * @return
     */
    @Override
    public PageUtils pageQuery(WareSkuVO vo) {
        PageUtils pageUtils = PageUtils.selectPage(baseMapper, vo, WmsWareSku.class);
        return pageUtils;
    }

    /**
     * 获取sku库存
     *
     * @param skuIds
     * @return
     */
    @Override
    public List<SkuStockVO> getSkuStock(List<Long> skuIds) {
        List<WmsWareSku> wmsWareSkus = baseMapper.selectList(new LambdaQueryWrapper<WmsWareSku>().in(WmsWareSku::getSkuId, skuIds));
        List<SkuStockVO> voList = new ArrayList<>();
        if (StringUtils.isEmpty(wmsWareSkus)){
            Iterator<Map.Entry<Long, List<WmsWareSku>>> iterator = wmsWareSkus.stream().collect(Collectors.groupingBy(WmsWareSku::getSkuId)).entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<Long, List<WmsWareSku>> next = iterator.next();
                Long skuId = next.getKey();
                List<WmsWareSku> value = next.getValue();
                int total = 0;
                for (WmsWareSku wmsWareSku : value) {
                    total = total + Optional.ofNullable(wmsWareSku.getStock()).orElse(0) - Optional.ofNullable(wmsWareSku.getStockLocked()).orElse(0);
                }
                SkuStockVO skuStockVO = new SkuStockVO(skuId, total, total > 0);
                voList.add(skuStockVO);
            }
        }
        return voList;
    }

    /**
     * 根据收货地址id计算运费
     *
     * @param addrId
     */
    @Override
    public MemberReceiveAddressTo getFreight(Long addrId) throws Exception {
        R<MemberReceiveAddressTo> toR = memberFeignService.getAddressById(addrId);
        if (toR.getCode() == 0){
            MemberReceiveAddressTo data = toR.getData();
            int freight =  Integer.parseInt(data.getPhone().substring(0,1)) + 10;
            data.setFreight(new BigDecimal(freight));
            return data;
        }
        return null;
    }

    /**
     * 生成订单锁库存
     *
     * @param stockTo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean lockStock(StockTo stockTo) {

        // 添加库存锁订单记录
        WmsWareOrderTask wareOrderTask = new WmsWareOrderTask();
        wareOrderTask.setOrderSn(stockTo.getOrderSn());
        wareOrderTaskService.save(wareOrderTask);

        // 查询所有存在该商品多余库存的厂库
        List<SkuStockTo> skuStockList = stockTo.getSkuStockList();
        // 查询存在库存的仓库
        List<WareHasStock> list = skuStockList.stream().map(entry -> {
            Long skuId = entry.getSkuId();
            List<WmsWareSku> hasStock = baseMapper.listHasStock(skuId);
            // 如果所有仓库都无库存，则抛出异常
            if (StringUtils.isEmpty(hasStock)){
                throw new HasNoStockException(skuId);
            }
            return new WareHasStock(skuId, hasStock);
        }).collect(Collectors.toList());

        List<WmsWareOrderTaskDetail> detailList = new ArrayList<>();

        // 遍历仓库锁定库存
        for (SkuStockTo skuStockTo : skuStockList) {
            Long skuId = skuStockTo.getSkuId();
            Integer num = skuStockTo.getNum();
            // 已经满足需要锁定的库存
            boolean hasStock = false;
            // 遍历所有存在该商品多余库存的厂库
            for (WareHasStock wareHasStock : list) {
                // 遍历该商品所有存在库存的厂库
                List<WmsWareSku> wareSkuList = wareHasStock.getWareSkuList();
                for (WmsWareSku wmsWareSku : wareSkuList) {
                    Long wareId = wmsWareSku.getWareId();
                    Integer stock = wmsWareSku.getStock();
                    // 锁定库存
                    int count = baseMapper.lockStock(skuId, wareId, num);
                    if (count > 0){
                        // 添加锁定记录
                        WmsWareOrderTaskDetail wareOrderTaskDetail = new WmsWareOrderTaskDetail();
                        wareOrderTaskDetail.setSkuId(skuId);
                        wareOrderTaskDetail.setSkuNum(num);
                        wareOrderTaskDetail.setTaskId(wareOrderTask.getId());
                        wareOrderTaskDetail.setWareId(wareId);
                        wareOrderTaskDetail.setLockStatus(1);
                        wareOrderTaskDetailService.save(wareOrderTaskDetail);
                        detailList.add(wareOrderTaskDetail);

                        num = num - stock;
                        if (num <= 0){
                            // 该仓库库存已经满足数量
                            hasStock = true;
                            break;
                        }
                    }
                }
                if (hasStock){
                    break;
                }
            }
            if (num > 0){
                // 代表所有的仓库库存都不够
                throw new HasNoStockException(skuId);
            }
        }

        if (StringUtils.isNotEmpty(detailList)){
            List<Long> detailsIds = detailList.stream().map(entry -> entry.getId()).collect(Collectors.toList());
            // 给mq延迟队列发送消息
            rabbitTemplate.convertAndSend("stock-event-exchange", "stock.locked", new StockLockTo(wareOrderTask.getId(),detailsIds));
        }

        return true;
    }

    @Data
    @AllArgsConstructor
    public class WareHasStock {
        /** 商品id **/
        private Long skuId;
        /** 存在库存的仓库id **/
        private List<WmsWareSku> wareSkuList;
    }


    /**
     * 订单解锁库存
     *
     * @param detail
     */
    @Override
    public void unLockStock(WmsWareOrderTaskDetail detail) {
        baseMapper.unLockStock(detail);
    }

    /**
     * 订单扣减库存
     *
     * @param detail
     */
    @Override
    public void deductionStock(WmsWareOrderTaskDetail detail) {
        baseMapper.deductionStock(detail);
    }
}




